home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 1 Issue 2
/
PDCD-1 - Issue 02.iso
/
_utilities
/
utilities
/
003
/
motorola
/
Sources
/
c
/
symtab
< prev
next >
Wrap
Text File
|
1993-07-18
|
19KB
|
497 lines
#include <string.h>
#include <stdio.h>
#include "mselect.h" /*external selection of microprocessor symbol table*/
#include "proto.h"
#include "as.h"
#include "structs.h"
#ifdef HC11
#include "table11.h"
#else
#include "table5.h"
#endif
#include "extvars.h"
/*
* pseudo --- pseudo op processing
*/
#define RMB 0 /* Reserve Memory Bytes */
#define FCB 1 /* Form Constant Bytes */
#define FDB 2 /* Form Double Bytes (words) */
#define FCC 3 /* Form Constant Characters */
#define ORG 4 /* Origin */
#define EQU 5 /* Equate */
#define ZMB 6 /* Zero memory bytes */
#define FILL 7 /* block fill constant bytes */
#define OPT 8 /* assembler option */
#define NULL_OP 9 /* null pseudo op */
#define PAGE 10 /* new page */
#define INCLUDE 11 /* include <file> or "file" ver TER_2.0 */
#define END 12 /* include <file> terminator ver TER_2.0 */
#define IFD 13 /* if define <symbol> ver TER_2.0 */
#define IFND 14 /* if not define <symbol> ver TER_2.0 */
#define ELSE 15 /* else (for IF statements) ver TER_2.0 */
#define ENDIF 16 /* endif (for IF statements) ver TER_2.0 */
#define BSS 17 /* block storage segment (RAM) ver TER_2.09 */
#define CODE 18 /* code segment ver TER_2.09 25 Jul 89 */
#define DATA 19 /* data segment ver TER_2.09 25 Jul 89 */
#define AUTO 20 /* data segment ver TER_2.09 25 Jul 89 */
struct oper pseudo[] = {
"=", PSEUDO, EQU, 0, /* ver TER_2.09 25 Jul 89 */
"auto", PSEUDO, AUTO, 0,/* ver TER_2.09 25 Jul 89 */
"bss", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
"bsz", PSEUDO, ZMB, 0,
"code", PSEUDO, CODE, 0,/* ver TER_2.09 25 Jul 89 */
"data", PSEUDO, DATA, 0,/* ver TER_2.09 25 Jul 89 */
"else", PSEUDO, ELSE, 0,/* ver TER_2.0 6/17/89 */
"end", PSEUDO, END, 0, /* ver TER_2.0 6/17/89 */
"endif", PSEUDO, ENDIF, 0, /* ver TER_2.0 6/17/89 */
"equ", PSEUDO, EQU, 0,
"fcb", PSEUDO, FCB, 0,
"fcc", PSEUDO, FCC, 0,
"fdb", PSEUDO, FDB, 0,
"fill", PSEUDO, FILL, 0,
"ifd", PSEUDO, IFD, 0, /* ver TER_2.0 6/17/89 */
"ifnd", PSEUDO, IFND, 0,/* ver TER_2.0 6/17/89 */
"include", PSEUDO, INCLUDE, 0, /* ver TER_2.0 6/17/89 */
"nam", PSEUDO, NULL_OP, 0,
"name", PSEUDO, NULL_OP, 0,
"opt", PSEUDO, OPT, 0,
"org", PSEUDO, ORG, 0,
"pag", PSEUDO, PAGE, 0,
"page", PSEUDO, PAGE, 0,
"ram", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
"rmb", PSEUDO, RMB, 0,
"spc", PSEUDO, NULL_OP, 0,
"ttl", PSEUDO, NULL_OP, 0,
"zmb", PSEUDO, ZMB, 0
};
/*
* do_pseudo --- do pseudo op processing
*/
void
do_pseudo(int op)
/* int op; which op */
{
char fccdelim;
int fill;
int c; /* test variable ver TER_2.0 6/18/89 */
char *savept; /* savept is pointer to string save */
FILE *FdTemp; /* ver TER_2.0 6/17/89 */
/*
* void pouterror(), NewPage(), IfMachine();
*//* rel TER_2.0 6/18/89 */
/* void PC_Exchange(); *//* ver TER_2.09 25 Jul 89 */
if (op != EQU && *Label)
install(Label, Pc);
P_force++;
#ifdef DEBUG3
printf("%s, line no. ", Argv[Cfn]); /* current file name */
printf("%d: ", Line_num); /* current line number */
printf(" Pseudo Op=%u\n", op);
#endif
switch (op) {
case RMB: /* reserve memory bytes */
if (eval()) {
Pc += Result;
f_record(); /* flush out bytes */
} else
error("Undefined Operand during Pass One");
break;
case ZMB: /* zero memory bytes */
if (eval())
while (Result--)
emit(0);
else
error("Undefined Operand during Pass One");
break;
case FILL: /* fill memory with constant */
eval();
fill = Result;
if (*Optr++ != ',')
error("Bad fill");
else {
Optr = skip_white(Optr);
eval();
while (Result--)
emit(fill);
}
break;
case FCB: /* form constant byte(s) */
do {
Optr = skip_white(Optr);
eval();
if (Result > 0xFF) {
if (!Force_byte)
warn("Value truncated");
Result = lobyte(Result);
}
emit(Result);
} while (*Optr++ == ',');
break;
case FDB: /* form double byte(s) */
do {
Optr = skip_white(Optr);
eval();
eword(Result);
} while (*Optr++ == ',');
break;
case FCC: /* form constant characters */
if (*Operand == EOS)
break;
/* Optr++;*/
fccdelim = *Optr++;
if ((fccdelim != SQUOT) && (fccdelim != DQUOT))
{error("Missing Delimiter - \' or \" expected");
break;}
/* putchar ( fccdelim );*/
while (*Optr != EOS && *Optr != fccdelim)
emit(*Optr++);
if (*Optr == fccdelim)
{Optr++;}
else
{error("Missing Delimiter");}
break;
case ORG: /* origin */
if (eval()) {
Old_pc = Pc = Result;
f_record(); /* flush out any bytes */
} else
error("Undefined Operand during Pass One");
break;
case EQU: /* equate */
if (*Label == EOS) {
error("EQU requires label");
break;
}
if (eval()) {
install(Label, Result);
Old_pc = Result; /* override normal */
} else
error("Undefined Operand during Pass One");
break;
case OPT: /* assembler option */
P_force = 0;
if (head(Operand, "l"))
Lflag = 1;
else if (head(Operand, "nol"))
Lflag = 0;
else if (head(Operand, "c")) {
Cflag = 1;
Ctotal = 0;
} else if (head(Operand, "noc"))
Cflag = 0;
else if (head(Operand, "contc")) {
Cflag = 1;
} else if (head(Operand, "s"))
Sflag = 1;
else if (head(Operand, "cre"))
CREflag = 1;
else if (head(Operand, "p50")) /* turn on page flag */
Pflag50 = 1; /* ver (TER) 2.02 19 Jun 89 */
else if (head(Operand, "crlf")) /* add <CR> <LF> to */
CRflag = 1; /* S record ver TER_2.08 */
else if (head(Operand, "nnf")) /* no extra line no. */
nfFlag = 0; /* w include files ver TER_2.08 */
else
error("Unrecognized OPT");
break;
case PAGE: /* go to a new page */
P_force = 0;
N_page = 1;
if (Pass == 2)
if (Lflag)
NewPage();
break;
case NULL_OP: /* ignored psuedo ops */
P_force = 0;
break;
case INCLUDE: /* case INCLUDE added ver TER_2.0 6/17/89 */
P_force = 0; /* no PC in printed output */
if ((c = FNameGet(InclFName)) == 0)
error("Improper INCLUDE statement");
else {
if (FdCount > MAXINCFILES)
error("too many INCLUDE files");
else {
if ((FdTemp = fopen(InclFName, "r")) == 0) {
warn(strcat("can't open INCLUDE file ", InclFName));
} else {
if ((savept = strsave(InclFName)) == 0)
error("out of memory for INCLUDE file name");
else {
InclFiles[FdCount].fp = Fd; /* save current fp */
if (nfFlag) {
InclFiles[FdCount].line_num = Line_num;
/*
* save current line
* count
*/
Line_num = 0; /* reset for new file */
}
InclFiles[FdCount].name = Argv[Cfn];
/*
* save pointer to current
* name
*/
Argv[Cfn] = savept;
/*
* now replace pointer to
* current name with pointer
* to name of Include file
*/
Fd = FdTemp; /* now replace current
* file with INCLUDE fp */
FdCount++; /* and increment "stack" */
#ifdef DEBUG2
printf("pseudo INCLUDE: FdCount=%d\n", FdCount);
printf(" new input file pointer=%d\n", Fd);
printf(" new file name=%s\n", Argv[Cfn]);
#endif
}
}
}
}
break;
case END:
P_force = 0;
if (FdCount > 0) { /* skip END statements in files
* received from CLI arguments */
fclose(Fd); /* close file from this level nest */
FdCount--; /* "pop stack" */
Fd = InclFiles[FdCount].fp; /* restore fp from
* nested stack */
if (nfFlag)
Line_num = InclFiles[FdCount].line_num;
Argv[Cfn] = InclFiles[FdCount].name;
/* restore file name pointer */
#ifdef DEBUG2
printf("pseudo END: FdCount=%d\n", FdCount);
printf(" new input file pointer=%d\n", Fd);
printf(" new file name=%s\n", Argv[Cfn]);
#endif
}
break;
case IFD:
#ifdef DEBUG3
printf("case IFD: in pseudo\n");
#endif
P_force = 0;
c = eval_ifd();
IfMachine(c);
break;
case IFND:
P_force = 0;
c = eval_ifnd();
IfMachine(c);
break;
case ELSE:
P_force = 0;
IfMachine(IF_ELSE);
break;
case ENDIF:
P_force = 0;
IfMachine(IF_ENDIF);
break;
case CODE: /* CODE,DATA,BSS,AUTO ver TER_2.09 */
PC_Exchange(0);
break;
case DATA:
PC_Exchange(1);
break;
case BSS:
PC_Exchange(2);
break;
case AUTO:
PC_Exchange(3);
break;
default:
fatal("Pseudo error");
break;
}
}
/*
* PC_Exchange --- Save current PC and recover requested one added ver
* TER_2.09
*/
void
PC_Exchange(int PC_ptr_new)
/* int PC_ptr_new; request 0=CODE,1=DATA,2=BSS */
{
P_force = 0; /* no PC in output cuz wrong first time (?) */
PC_Save[PC_ptr] = Pc; /* save current PC */
PC_ptr = PC_ptr_new; /* remember which one we're using */
Old_pc = Pc = PC_Save[PC_ptr]; /* recover the one requested */
f_record(); /* flush out any bytes, this is really an ORG */
}
/* pseudo module ends here */
/*
* install --- add a symbol to the table
*/
int
install(char *str, int val)
{
struct link *lp;
struct nlist *np, *p, *backp;
int i;
/* char *LastChar(); *//* ver TER_2.0 */
if (!alpha(*str)) {
error("Illegal Symbol Name");
return (NO);
}
if ((np = lookup(str)) != NULL) {
if (*LastChar(str) == '@') { /* redefinable symbol ver
* TER_2.0 */
np->def = val; /* redefined */
return (YES);
}
if (Pass == 2) {
np->def2 = 2; /* defined for this pass=Pass ver
* TER_2.0 */
if (np->def == val)
return (YES);
else {
error("Phasing Error");
return (NO);
}
}
error("Symbol Redefined");
return (NO);
}
/* enter new symbol */
#ifdef DEBUG
printf("Installing %s as %d\n", str, val);
#endif
np = (struct nlist *) alloc(sizeof(struct nlist));
if (np == (struct nlist *) ERR) {
error("Symbol table full");
return (NO);
}
np->name = alloc(strlen(str) + 1);
if (np->name == (char *) ERR) {
error("Symbol table full");
return (NO);
}
strcpy(np->name, str);
np->def = val;
np->def2 = 1; /* defined for this pass=Pass ver TER_2.0 */
np->Lnext = NULL;
np->Rnext = NULL;
lp = (struct link *) alloc(sizeof(struct link));
np->L_list = lp;
lp->L_num = Line_num;
lp->next = NULL;
p = root;
backp = NULL;
while (p != NULL) {
backp = p;
i = strcmp(str, p->name);
if (i < 0)
p = p->Lnext;
else
p = p->Rnext;
}
if (backp == NULL)
root = np;
else if (strcmp(str, backp->name) < 0)
backp->Lnext = np;
else
backp->Rnext = np;
return (YES);
}
/*
* lookup --- find string in symbol table
*/
struct nlist *
lookup(char *name)
{
struct nlist *np;
int i;
char *c; /* ver TER_2.0 */
c = name; /* copy symbol pointer */
while (alphan(*c)) /* search for end of symbol */
c++; /* next char */
*c = EOS; /* disconnect anything after for good compare */
/* end of mods for ver TER_2.0 */
np = root; /* and now go on and look for symbol */
while (np != NULL) {
i = strcmp(name, np->name);
if (i == 0) {
Last_sym = np->def;
return (np);
} else if (i < 0)
np = np->Lnext;
else
np = np->Rnext;
}
Last_sym = 0;
/*
* if (Pass == 2) error ("symbol Undefined on pass 2");
*/
/* commented out ver TER_2.0 2 Jul 89 */
/* function used in IFD */
return (NULL);
}
#define NMNE (sizeof(table)/ sizeof(struct oper))
#define NPSE (sizeof(pseudo)/ sizeof(struct oper))
/*
* mne_look --- mnemonic lookup
*
* Return pointer to an oper structure if found. Searches both the machine
* mnemonic table and the pseudo table.
*/
struct oper *
mne_look(char *str)
{
struct oper *low, *high, *mid;
int cond;
/* Search machine mnemonics first */
low = &table[0];
high = &table[NMNE - 1];
while (low <= high) {
mid = low + (high - low) / 2;
if ((cond = strcmp(str, mid->mnemonic)) < 0)
high = mid - 1;
else if (cond > 0)
low = mid + 1;
else
return (mid);
}
/* Check for pseudo ops */
low = &pseudo[0];
high = &pseudo[NPSE - 1];
while (low <= high) {
mid = low + (high - low) / 2;
if ((cond = strcmp(str, mid->mnemonic)) < 0)
high = mid - 1;
else if (cond > 0)
low = mid + 1;
else
return (mid);
}
return (NULL);
}